package com.flca.dbs.appengine;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

import com.flca.frw.dao.Dao;
import com.flca.frw.dao.PersistenceType;
import com.flca.frw.dao.RegisterDatabase;

public class AppEngineDaoImpl implements Dao {

	private static final long serialVersionUID = 6859145331274345649L;

	private EntityManager em;

	/**
	 * this is NOT public. It is used bu the ConnectionMgrFactory
	 */
	AppEngineDaoImpl() {
	}

	public AppEngineDaoImpl(EntityManager aEmf) {
		em = aEmf;
	}
	
	public Object getObjectMgr() {
		return em;
	}
	
	public boolean isInTransaction() throws Exception  {
		if (em != null && em.getTransaction() != null) {
			return em.getTransaction().isActive();
		}
		return false;
	}

	public void commit() throws Exception {
		if (em != null && em.isOpen() && em.getTransaction() != null && em.getTransaction().isActive()) {
			em.getTransaction().commit();
		} else {
//			logError("commit called with EntityManager null");
		}
	}

	public void rollback() throws Exception {
		if (em != null && em.getTransaction() != null) {
			em.getTransaction().rollback();
		} else {
			logError("rollback called with EntityManager null");
		}
	}

	public void startTransaction() throws Exception {
		if (em != null && em.getTransaction() != null) {
			em.getTransaction().begin();
		} else {
			throw new NullPointerException("startTransaction called with EntityManager null");
		}
	}

	public Iterator<?> openByQuery(Class<?> aClass, String aSql, Object[] aArguments)  throws Exception 
	{
		if (em != null && em.getTransaction() != null) {
			Query qry = em.createQuery(aSql);
			if (aArguments != null) {
				for (int i = 0; i < aArguments.length; i++) {
					qry.setParameter(i + 1, aArguments[i]);
				}
			}
			List<?> list = qry.getResultList();
			return list.iterator();
		} else {
			throw new NullPointerException("openByQuery called with EntityManager null");
		}
	}

	public Iterator<?> openByQuery(String aSql, Object[] aArguments) throws Exception 
	{
		if (em != null && em.getTransaction() != null) {
			Query qry = em.createQuery(aSql);
			if (aArguments != null) {
				for (int i = 0; i < aArguments.length; i++) {
					qry.setParameter(i, aArguments[i]);
				}
			}
			List<?> list = qry.getResultList();
			return list.iterator();
		} else {
			throw new NullPointerException("openByQuery called with EntityManager null");
		}
	}
	
	public void deleteAll(Class<?> aClass) throws Exception {
		System.out.println("not implemented yet");
	}
	
	public PersistenceType technology() {
		return PersistenceType.JPA; 
	}
	
	private void logError(String msg) {
		System.out.println(msg);
	}


	public Dao buildDao(RegisterDatabase aRegDbs) 
	{
		AppEngineDaoImpl result = null;
		
		try {
	        Map<String, Object> map = new HashMap<String, Object>();
	        EntityManagerFactory emf;

//	        map.put("javax.persistence.nonJtaDataSource", "");
//			map.put("hibernate.connection.driver_class", dbsProps.getDriver());
//			map.put("hibernate.connection.username", dbsProps.getUsername());
//			map.put("hibernate.connection.password", dbsProps.getPassword());
//			map.put("hibernate.connection.url", dbsProps.getUrl());
			
			System.out.println("Creating new Entitymanager " + aRegDbs.getUrl());

			emf = Persistence.createEntityManagerFactory(aRegDbs.getUnitName(), map);
			EntityManager em = emf.createEntityManager();
			result = new AppEngineDaoImpl(em);
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}


}
